require 'depac-deployment/environment_configuration'
require 'depac-deployment/helper'
require 'depac-deployment/configure'
require 'depac-common/constants'
require 'depac-common/utils'
require 'yaml'

#action: create/add/update
#envConfig_NR_type: type configuration in newrelicConfigure
#nodeInfoMap_type: type configuration in nodeInfoMap object
#role: the target role which be handled currently 
def validateNRAppName(envConfig_NR_type, nodeInfoMap_type, action, role)

   passValidate = false
   count_of_node=nodeInfoMap_type[role].length
   
   count_of_appname=envConfig_NR_type[role].length

   if action == "create"
       if count_of_node.to_i == count_of_appname.to_i
           passValidate=true
       end
   elsif action == "add"
        count_of_idle=getAppNameCount(envConfig_NR_type[role], "idle")
        Depac::Log.write("INFO", "number of idle newrelic application name is #{count_of_idle}")     
        if count_of_idle.to_i == count_of_node.to_i      
           passValidate=true
        end     
   else
        count_of_occupied=getAppNameCount(envConfig_NR_type[role], "occupy") 
        Depac::Log.write("INFO", "number of occupied newrelic application name is #{count_of_occupied}")     
        if count_of_occupied.to_i == count_of_appname.to_i
           passValidate = true
        end
   end
   
   return passValidate  
end

def getAppNameCount(nrConfRoleOInfo, checkType)

     count = 0    
     if nrConfRoleOInfo != nil
           nrConfRoleOInfo.each do |appnode|
           
               key=appnode.keys[0]
               
               if checkType == "idle" and appnode[key] == "IP"             
                    count +=1                 
               end
               
               if checkType == "occupy" and appnode[key] != "IP"              
                    count +=1
               end              
           end
     end    
     return count
end

def getNRAppName(envConfig, type, role, idleIP, action)    
     idleAppName =nil     
     if (envConfig !=nil and envConfig['newrelicConfig'][type] and envConfig['newrelicConfig'][type][role]!=nil)
           appNameArr= envConfig['newrelicConfig'][type][role]
           Depac::Log.write("INFO", "appNameArr is: #{appNameArr}") 

           appNameArr.each do |appnode|
                appname=appnode.keys()[0] 

                if action == "update"
                   
                   if getExistNodeIPList(envConfig, type, role).index(appnode[appname]) !=nil
                      idleAppName = appname                      
                      appnode[appname] = idleIP                    
                      break      
                   end
                elsif action == "remove"
                   if appnode[appname] == idleIP
                      idleAppName=appname
                      appnode[appname] = "IP"
                      break
                   end
                else
                   if appnode[appname] == "IP"
                      idleAppName=appname
                      appnode[appname] = idleIP
                      break
                   end
                end
          end
     end  
     
     Depac::Log.write("INFO", "get idle application name for candidate node #{idleIP} is : #{idleAppName} ") 
     
     return idleAppName 
end

def getExistNodeIPList(envConfig, type, role)
      
      typeConfig=envConfig[type]

      nodeinfoArr=nil
      typeConfig.each do |roleInfo|
               if roleInfo['role'] == role
                     nodeinfoArr=roleInfo['node_info']
                     break
               end
      end

      Depac::Log.write("INFO", "getExistNodeIPList--> nodeinfoArr is: #{nodeinfoArr}")
      existNodeIPArray=[]
      
      if nodeinfoArr !=nil     
         nodeinfoArr.each do |node|
                existNodeIPArray.push(node['IP'])
         end     
      end
      Depac::Log.write("INFO", "exist node array of #{type}->#{role} is: #{existNodeIPArray}")  
   
      return existNodeIPArray
end


def getNodeCount(envConfig, role)
    if envConfig[Depac::CloudDeploymentConstants::RUNTIME_NODES][role] !=nil
          count= envConfig[Depac::CloudDeploymentConstants::RUNTIME_NODES][role][Depac::CloudDeploymentConstants::NODE_INFO]
          if count == nil
              count = envConfig[Depac::CloudDeploymentConstants::RUNTIME_NODES][role][Depac::CloudDeploymentConstants::NODE_INFO].length
          end
    end
end


#TODO: configure NewRelic with static application name
#action create/add/update
def configureNRAppName(nodeInfoMap, envConfig, action)
  
   Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
   if envConfig['newrelicEnablement'] == true      
      
    
       if envConfig['newrelicConfig'] !=nil && envConfig['newrelicConfig']['useStaticName'] == true
        
         Depac::Log.write("INFO", "Configuring newrelice static application name")
         Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
        
         typeArr = getEnvironmentTypes()
        
         typeArr.each do |type|       
             ["database", "jms", "appserver", "agent", "intg"].each do |role|
                 
                 #if validateNRAppName pass, that means application name be configured correct, we can configure nr appliation name now, if
                 #if not, that means application name configuration is incorrect, configurationNRAppName will be ingore and will out error log          
                 
                 if envConfig['newrelicConfig'][type] !=nil && nodeInfoMap[type] !=nil
                     if envConfig['newrelicConfig'][type][role] !=nil && nodeInfoMap[type][role] != nil
                        if validateNRAppName(envConfig['newrelicConfig'][type], nodeInfoMap[type], action, role)
                        
                                   configureNRAppName_internal(nodeInfoMap, envConfig, type, role, action, true)                             
                        end 
                     end 
                 end                          
            end       
         end
      else
         typeArr = getEnvironmentTypes()       
         typeArr.each do |type|       
             ["appserver"].each do |role|
                 if nodeInfoMap[type] !=nil && nodeInfoMap[type][role] !=nil
                         Depac::Log.write("INFO", "Configuring newrelice application name with current hostname for #{role}")
                         Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
                         configureNRAppName_internal(nodeInfoMap, envConfig,  type, role, action, false) 
                 end
             end 
         end      
      end       
  else
     Depac::Log.write("INFO", "ignore configure newrelic application name......")      
  end 
  Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
end


def configureNRAppName_internal(nodeInfoMap, envConfig, type, role, action, isStaticName)

   nodeInfoMap[type][role].each do |node|  
           if isStaticName == true                               
              appName=getNRAppName(envConfig, type, role, node['IP'], action)
           else
              appName=node['hostname']    
           end
           
           newrelicProxy = "default"
           
           if envConfig['newrelicConfig'] != nil && envConfig['newrelicConfig']['newrelix_proxyhost'] != nil
                newrelicProxy = envConfig['newrelicConfig']['newrelix_proxyhost']
           end
                                     
           if action == "remove"
                 Depac::Log.write("INFO", "release newrelice application name from #{node['IP']} under #{type}/#{role}......")
           else
                 Depac::Log.write("INFO", "configure static newrelic application name for node: #{node['IP']}  .....")                                  
                 cmdstr = "ssh -t -t -i #{Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH} root@#{node['IP']} -o StrictHostKeyChecking=no 'cd /migration;./updateNewRelicConfigure.sh #{appName} #{newrelicProxy}'"
                 Depac::Log.write("INFO", "Executing command: " + cmdstr)
                 output =  `#{cmdstr}`
                 Depac::Log.write("INFO", output)
                 Depac::Log.write("INFO", Depac::CloudDeploymentConstants::BORDER_LINE)
          end                                                                            
   end  
end